package android;

import android.app.Application;
import android.app.NotificationManager;
import android.app.Service;
import android.content.*;
import android.content.impl.SharedPreferencesImpl;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import io.reactivex.Scheduler;
import io.reactivex.rxjavafx.schedulers.JavaFxScheduler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author slc
 * @date 2022/03/30 下午 3:36
 */
public class VirtualAndroidUtils {
    private static final Map<String, ContentResolver> contentResolverMap = new ConcurrentHashMap<>();
    private static final Map<String, SharedPreferences> sharedPreferences = new ConcurrentHashMap<>();
    private static final Map<String, Service> serviceMap = new ConcurrentHashMap<>();
    private static final List<BroadcastReceiver> broadcastReceiverList = Collections.synchronizedList(new ArrayList<>());
    private static Context applicationContext;
    private static ContextIntercept contextIntercept;

    public final static Scheduler javaFxScheduler;

    static {
        javaFxScheduler = JavaFxScheduler.platform();
    }

    public static void init() {
        init("android.slc.ssfx");
    }

    public static void init(String packageName) {
        applicationContext = new Application();
        applicationContext.setPackageName(packageName);
        PackageManager packageManager = new PackageManager();
        PackageInfo packageInfo = new PackageInfo("1.0");
        packageManager.addPackageInfo(applicationContext.getPackageName(), packageInfo);
        applicationContext.setPackageManager(packageManager);

        ConnectivityManager connectivityManager = new ConnectivityManager();
        serviceMap.put(ConnectivityManager.class.getName(), connectivityManager);
        serviceMap.put(Context.CONNECTIVITY_SERVICE, connectivityManager);
        NotificationManager notificationManager = new NotificationManager();
        serviceMap.put(Context.NOTIFICATION_SERVICE, notificationManager);
        serviceMap.put(NotificationManager.class.getName(), notificationManager);
    }

    public static Context getApp() {
        return applicationContext;
    }

    public static ContentResolver getContentResolver(String key) {
        return contentResolverMap.computeIfAbsent(key, k -> new ContentResolver());
    }

    public static SharedPreferences getSharedPreferences(String key) {
        return sharedPreferences.computeIfAbsent(key, k -> new SharedPreferencesImpl());
    }

    public static void startService(Context context, Intent intent) {
        javaFxScheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                try {
                    Service service = serviceMap.get(intent.getComponent().getClassName());
                    if (service == null) {
                        service = (Service) Class.forName(intent.getComponent().getClassName()).newInstance();
                        completeBasicInformation(context, service);
                        serviceMap.put(intent.getComponent().getClassName(), service);
                        service.onCreate();
                    }
                    onInterceptContext(service, intent);
                    service.onStartCommand(intent, 0, 0);
                } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {

                }
            }
        });

    }

    public static void stopService(Context context, Intent intent) {
        javaFxScheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                Service service = serviceMap.get(intent.getComponent().getClassName());
                if (service != null) {
                    service.onDestroy();
                    serviceMap.remove(intent.getComponent().getClassName());
                }
            }
        });

    }

    public static final <T> T getSystemService(Class<T> serviceClass) {
        return (T) getSystemService(serviceClass.getName());
    }

    public static Object getSystemService(String name) {
        return serviceMap.get(name);
    }

    public static void registerReceiver(Context context, BroadcastReceiver broadcastReceiver,
                                        IntentFilter intentFilter) {
        completeBasicInformation(context, context);
        broadcastReceiver.addMonitorActions(intentFilter.getActionList());
        broadcastReceiverList.add(broadcastReceiver);
    }


    public static void unregisterReceiver(Context context, BroadcastReceiver broadcastReceiver) {
        broadcastReceiverList.remove(broadcastReceiver);
    }

    public static void sendBroadcast(Context context, Intent intent) {
        javaFxScheduler.scheduleDirect(new Runnable() {
            @Override
            public void run() {
                for (BroadcastReceiver broadcastReceiver : broadcastReceiverList) {
                    broadcastReceiver.notifyReceive(context, intent);
                }
            }
        });
    }

    public static void completeBasicInformation(Context src, Context target) {
        target.setPackageName(src.getPackageName());
        target.setPackageManager(src.getPackageManager());
    }

    public static void setContextIntercept(ContextIntercept contextIntercept) {
        VirtualAndroidUtils.contextIntercept = contextIntercept;
    }

    public static ContextIntercept getContextIntercept() {
        return contextIntercept;
    }

    /**
     * 上下文环境拦截器
     */
    public interface ContextIntercept {
        void onIntercept(Context context, Intent intent);
    }

    /**
     * 拦截CIMPushService的绑定方法更改设备类型
     *
     * @param context
     * @param intent
     */
    private static void onInterceptContext(Context context, Intent intent) {
        if (getContextIntercept() != null) {
            getContextIntercept().onIntercept(context, intent);
        }
    }

    /*private static void interceptSendBindMessage(Context context, Intent intent) {
        if(getContextIntercept()!=null){
            getContextIntercept().onIntercept(context,intent);
        }
        if (service instanceof CIMPushService) {
            if (StringUtils.equals("ACTION_SEND_REQUEST_BODY", intent.getAction())) {
                SentBody sentBody = (SentBody) intent.getSerializableExtra("KEY_SEND_BODY");
                if (CIMConstant.RequestKey.CLIENT_BIND.equals(sentBody.getKey())) {
                    sentBody.put("channel", "windows");
                }
            } else if (StringUtils.equals("ACTION_CREATE_CIM_CONNECTION", intent.getAction())) {
                long interval = intent.getLongExtra("KEY_DELAYED_TIME", 0);
                if (interval > 0) {
                    intent.putExtra("KEY_DELAYED_TIME", 3000L + new Random().nextInt(5000));
                }

            }
        }
    }*/
}
